home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 1997 September / Macworld (1997-09).dmg / Shareware World / Utilities / Text Processing / Alpha / Tcl / Modes / htmlExtra.tcl < prev    next >
Text File  |  1997-01-21  |  19KB  |  682 lines

  1. #===============================================================================
  2. #
  3. #     htmlExtra.tcl
  4. #
  5. #    Part of HTML mode 1.4
  6. #
  7. #     Routines for giving attributes in the status bar.
  8. #
  9. #    Copyright 1996, 1997 by Johan Linde <jl@theophys.kth.se>.
  10. #    This software may be used freely, and distributed freely, as long as 
  11. #    the receiver is not obligated in any way by receiving it.
  12. #
  13. #    If you make improvements to this file, please share them!
  14. #
  15. #===============================================================================
  16.  
  17. # Opening or only tag of an element - include attributes
  18. # Status bar for each attribute.
  19. # Return empty string if user skips an attribute which must be used.
  20. proc htmlOpenElemLoop {elem used wrPos} {
  21.     global htmlActiveElem htmlActiveUsed htmlActiveAttr htmlActiveCache
  22.     global HTMLmodeVars htmlPackageToUse htmlElemEventHandler1
  23.     global htmlURLAttr htmlColorAttr htmlWindowAttr htmlWrapPos
  24.     global htmlSpecURL htmlSpecColor htmlSpecWindow  htmlActiveWidth htmlActiveHeight
  25.     
  26.     set promptNoisily $HTMLmodeVars(promptNoisily)
  27.     
  28.     if {![string length $used]} {set used $elem}
  29.     set elem [string toupper $elem]
  30.     set used [string toupper $used]
  31.     
  32.     set htmlActiveUsed $used
  33.     set htmlActiveElem $elem
  34.     set text "<"
  35.     append text [htmlSetCase $elem]
  36.  
  37.     # if there are attributes to ask about, do so
  38.     set reqatts [htmlGetRequired $used]
  39.     set useatts [htmlGetUsed $used]
  40.     set askformore [htmlGetAttrMore $used]
  41.     set optatts [htmlGetOptional $used]
  42.     set NumberAttrs [htmlGetNumber $used]
  43.     # Add missing required attributes.
  44.     foreach a $reqatts {
  45.         if {[lsearch -exact $useatts $a] < 0} {
  46.             set useatts "$a $useatts"
  47.         }
  48.     }
  49.     # Remove extra attributes
  50.     foreach a $useatts {
  51.         if {[lsearch -exact $reqatts $a] < 0 && [lsearch -exact $optatts $a] < 0} {
  52.             set where [lsearch -exact $useatts $a]
  53.             set useatts [lreplace $useatts $where $where]
  54.         }
  55.     }
  56.     
  57.     set allatts $useatts
  58.     set eventatts ""
  59.     # If the ask for more flag is set, add the rest of the attributes.
  60.     if {$askformore} {
  61.         foreach attr $optatts {
  62.             if {[lsearch -exact $useatts $attr] < 0} { lappend allatts $attr}
  63.         }
  64.         # optionally include event handlers
  65.         if {$HTMLmodeVars(inclEventHandler) && $htmlPackageToUse == 1 && \
  66.         [info exists htmlElemEventHandler1($used)]} {
  67.             set eventatts $htmlElemEventHandler1($used)
  68.             append allatts " " $eventatts
  69.         }
  70.     }
  71.     
  72.     # wrapping
  73.     set htmlWrapPos [expr $wrPos == -1 ? [lindex [posToRowCol [getPos]] 1] : $wrPos]
  74.     incr htmlWrapPos [expr [string length $text] + 1]
  75.     for {set i 0} {$i < [llength $allatts]} {incr i} {
  76.     
  77.         set attr [lindex $allatts $i]
  78.         if {$i == [llength $useatts]} { 
  79.             # it's time to ask if more is wanted
  80.             if {$promptNoisily} {beep}
  81.             set more ""
  82.             if {$used == "LI IN UL" || $used == "LI IN OL"} {
  83.                 set pr "LI:"
  84.             } else {
  85.                 set pr "${used}:"
  86.             }
  87.             while {[catch {statusPrompt "$pr More attributes? \[n\] " htmlStatusAskYesOrNo} more]} {
  88.                 if {$more == "Cancel all!"} {
  89.                     message "Cancel"
  90.                     error
  91.                 }
  92.             }
  93.             if {$more != "yes"} { break }
  94.         }
  95.         if {[lsearch -exact $reqatts $attr] >= 0} {
  96.             set required 1
  97.         } else {
  98.             set required 0
  99.         }
  100.         set htmlActiveAttr $attr
  101.         set a2 [string trimright $attr =]
  102.         if {[string index $attr [expr [string length $attr] - 1]] == "="} {
  103.             if {([lsearch -exact $htmlURLAttr $attr] >= 0 && [lsearch -exact $htmlSpecURL "${used}!=$a2"] < 0) || \
  104.             [lsearch -exact $htmlSpecURL "${used}=$a2"] >= 0} { 
  105.                 # URL attibute
  106.                 set htmlActiveCache URLs
  107.                 if {[catch {htmlAskURL $attr $required} v]} {
  108.                     if {$v != "Skip rest!"} {
  109.                         error
  110.                     } elseif {!$required} {
  111.                         set i [llength $allatts]
  112.                     } else {
  113.                         set v ""
  114.                     }
  115.                 } elseif {[string length $v]} {
  116.                     append text [htmlWrapTag "[htmlSetCase $attr][htmlAddQuotes [htmlURLescape2 $v]]"]
  117.                 }
  118.             } elseif {([lsearch -exact $htmlColorAttr $attr] >= 0 && [lsearch -exact $htmlSpecColor "${used}!=$a2"] < 0) || \
  119.             [lsearch -exact $htmlSpecColor "${used}=$a2"] >= 0} { 
  120.                 # Color attribute
  121.                 if {[catch {htmlAskColor $attr $required} v]} {
  122.                     if {$v != "Skip rest!"} {
  123.                         error
  124.                     } elseif {!$required} {
  125.                         set i [llength $allatts]
  126.                     } else {
  127.                         set v ""
  128.                     }
  129.                 } elseif {[string length $v]} {
  130.                     append text [htmlWrapTag "[htmlSetCase $attr][htmlAddQuotes $v]"]
  131.                 }
  132.             } elseif {([lsearch -exact $htmlWindowAttr $attr] >= 0 && [lsearch -exact $htmlSpecWindow "${used}!=$a2"] < 0) || \
  133.             [lsearch -exact $htmlSpecWindow "${used}=$a2"] >= 0} { 
  134.                 # Window attribute
  135.                 set htmlActiveCache windows
  136.                 if {[catch {htmlAskURL $attr $required} v]} {
  137.                     if {$v != "Skip rest!"} {
  138.                         error
  139.                     } elseif {!$required} {
  140.                         set i [llength $allatts]
  141.                     } else {
  142.                         set v ""
  143.                     }
  144.                 } elseif {[string length $v]} {
  145.                     append text [htmlWrapTag "[htmlSetCase $attr][htmlAddQuotes $v]"]
  146.                 }
  147.             } elseif {[lsearch $NumberAttrs "$attr*"] >= 0} { 
  148.                 # Number attribute
  149.                 if {[catch {htmlAskNumber $used $attr $required} v]} {
  150.                     if {$v != "Skip rest!"} {
  151.                         error
  152.                     } elseif {!$required} {
  153.                         set i [llength $allatts]
  154.                     } else {
  155.                         set v ""
  156.                     }
  157.                 } elseif {[string length $v]} {
  158.                     append text [htmlWrapTag "[htmlSetCase $attr][htmlAddQuotes $v]"]
  159.                 }
  160.             } else { 
  161.                 # other attribute
  162.                 if {$promptNoisily} {beep}
  163.                 if {[catch {htmlStatusAskAttr $used $attr $required} v]} {
  164.                     if {$v != "Skip rest!"} {
  165.                         error
  166.                     } elseif {!$required} {
  167.                         set i [llength $allatts]
  168.                     } else {
  169.                         set v ""
  170.                     }
  171.                 } elseif {[string length $v]} {
  172.                     htmlOpenExtraThings $used $attr $v
  173.                     if {[lsearch -exact $eventatts $attr] < 0} {
  174.                         set attr [htmlSetCase $attr]
  175.                     }
  176.                     append text [htmlWrapTag "$attr[htmlAddQuotes $v]"]
  177.                 }
  178.             }
  179.             if {![string length $v] && $required } {
  180.                 alertnote "You must give $attr a value."
  181.                 incr i -1
  182.             } 
  183.         } else { 
  184.             # yes-no attribute
  185.             if {$promptNoisily} {beep}
  186.             set v ""
  187.             while {[catch {statusPrompt "${used}:$attr \[n\] " htmlStatusAskYesOrNo} v]} {
  188.                 if {$v == "Cancel all!"} {
  189.                     message "Cancel"
  190.                     error
  191.                 }
  192.                 if {$v == "Skip rest!"} {
  193.                     set i [llength $allatts]
  194.                     break
  195.                 }
  196.             }
  197.             if {$v == "yes"} {append text [htmlWrapTag [htmlSetCase $attr]]}
  198.         }
  199.     }
  200.  
  201.     # Some tests that input is ok.
  202.     if {[htmlFontBaseTest $text "message"]} {beep; set text ""}
  203.     if {$elem == "A" && [htmlATest $text "message"]} {beep; set text ""}
  204.     if {$elem == "FRAMESET" && [htmlFramesetTest $text "message"]} {beep; set text ""}
  205.     if {$elem == "SPACER" && [htmlSpacerTest $text "message"]} {beep; set text ""}
  206.     if {$elem == "AREA" && [htmlAreaTest $text "message"]} {beep; set text ""}
  207.     if {[string length $text] } {append text ">"}
  208.     catch {unset htmlActiveUsed}
  209.     catch {unset htmlActiveElem}
  210.     catch {unset htmlActiveAttr}
  211.     catch {unset htmlActiveCache}
  212.     catch {unset htmlActiveWidth}
  213.     catch {unset htmlActiveHeight}
  214.     return ${text}
  215. }
  216.  
  217. # Choose a color name or add a color number
  218.  
  219. proc htmlAskColor {attr required} {
  220.     global  HTMLmodeVars htmlColorTabSeen htmlActiveUsed htmlColorName
  221.     global  basicColors htmluserColors htmlColors htmlActiveColor
  222.     
  223.     set promptNoisily    $HTMLmodeVars(promptNoisily)
  224.     
  225. # put users colours first
  226.     set htmlColors [lsort [array names htmluserColors]]
  227.      append htmlColors " " $basicColors
  228.      
  229.      while {1} {
  230.          # Loop until input is valid or everything is cancelled, then something is returned
  231.          if {$promptNoisily} {beep}
  232.          set htmlColorTabSeen 0
  233.          set pr ""
  234.          if {!$required} { set pr "(optional) "}
  235.          append pr ${htmlActiveUsed}:${attr}
  236.          while {[catch {statusPrompt $pr htmlColorStatusFunc} r]} {
  237.              if {$r == "Cancel all!"} {
  238.                  message "Cancel"
  239.                  error
  240.              }
  241.              if {$r == "Continue!"} {
  242.                  set r $htmlActiveColor
  243.                  unset htmlActiveColor
  244.                  break
  245.              }
  246.              if {$r == "Skip rest!"} {error "Skip rest!"}
  247.          }
  248.          set r [string trim $r]
  249.          if {![string length $r]} {return}
  250.          # Users own color?
  251.          if {[info exists htmluserColors($r)]} {return $htmluserColors($r)}
  252.          # Predefined color?
  253.          if {[info exists htmlColorName($r)]} {
  254.              return $htmlColorName($r)
  255.          } else {
  256.              set col [htmlCheckColorNumber $r]
  257.              if {$col != 0} {
  258.                  return $col
  259.              } else {
  260.                  alertnote "$r is not a valid color number. It should be of the form #RRGGBB."
  261.              }
  262.          }
  263.      }
  264. }
  265.  
  266. proc htmlColorStatusFunc {curr c} {
  267.     global  htmlActiveAttr htmlColorTabSeen htmlColorName
  268.     global htmlColors htmlActiveColor htmlActiveUsed
  269.     
  270.     if {$c == "\032"} {
  271.         error "Cancel all!"
  272.     }
  273.     if {$c == "\021"} {error "Skip rest!"}
  274.     # ctrl-f is new color.
  275.     if {$c == "\006"} {
  276.         set newcolor [htmlAddNewColor]
  277.         if {[string length $newcolor]} {
  278.             set htmlActiveColor $newcolor
  279.             error "Continue!"
  280.         } else {
  281.             return
  282.         }
  283.     }
  284.     
  285.     if {$c != "\t"} {
  286.         set htmlColorTabSeen 0
  287.         return $c
  288.     }
  289.  
  290.     set matches {}
  291.     set attr $htmlActiveAttr
  292.     foreach w $htmlColors {
  293.         if {[string match "$curr*" $w]} {
  294.             lappend matches $w
  295.         }
  296.     }
  297.     if {![llength $matches]} {
  298.         beep
  299.     } else {
  300.         if {$htmlColorTabSeen} {
  301.             if {[catch {listpick -p ${htmlActiveUsed}:${htmlActiveAttr} $matches} ret]} {
  302.                 set ret ""
  303.             }
  304.             if {[string length $ret]} {
  305.                 set htmlActiveColor $ret
  306.                 error "Continue!"
  307.             }
  308.             set htmlColorTabSeen 0
  309.         } else {
  310.             set htmlColorTabSeen 1
  311.             set ret [string range [largestPrefix $matches] [string length $curr] end]
  312.         }
  313.         return $ret
  314.     }
  315.     return
  316. }
  317.  
  318.  
  319. # HREF attributes are handled as a listpick from a cached list
  320. proc htmlAskURL {attr required} {
  321.     global htmlURLTabSeen
  322.     global HTMLmodeVars htmlActiveUsed htmlActiveCache htmlActiveURL
  323.     
  324.     if {$HTMLmodeVars(promptNoisily)} {beep}
  325.     set htmlURLTabSeen 0
  326.     if {!$required} { set pr "(optional) "}
  327.     append pr ${htmlActiveUsed}:${attr}
  328.     while {[catch {statusPrompt $pr htmlURLStatusFunc} r]} {
  329.         if {$r == "Cancel all!"} {
  330.             message "Cancel"
  331.             error
  332.         }
  333.         if {$r == "Continue!"} {
  334.             set r $htmlActiveURL
  335.             unset htmlActiveURL
  336.             break
  337.         }
  338.         if {$r == "Skip rest!"} {error "Skip rest!"}
  339.     }
  340.     set r [string trim $r]
  341.     htmlAddToCache $htmlActiveCache $r
  342.     return $r
  343. }
  344.  
  345.  
  346. proc htmlURLStatusFunc {curr c} {
  347.     global HTMLmodeVars  htmlActiveAttr htmlURLTabSeen htmlActiveCache htmlActiveURL
  348.     global htmlActiveUsed htmlActiveWidth htmlActiveHeight
  349.     
  350.     set htmlActiveWidth ""
  351.     set htmlActiveHeight ""
  352.     if {$c == "\032"} {
  353.         error "Cancel all!"
  354.     }
  355.     if {$c == "\021"} {error "Skip rest!"}
  356.     if {$htmlActiveCache == "windows"} {set URLs {_self _top _parent _blank}}
  357.     append URLs " " $HTMLmodeVars($htmlActiveCache)
  358.     
  359.     # ctrl-f for file dialog.
  360.     if {$c == "\006"} {
  361.         if {$htmlActiveCache == "windows"} {
  362.             beep
  363.             return
  364.         }
  365.         set newURL [htmlGetFile]
  366.         if {[string length $newURL]} {
  367.             set htmlActiveURL [lindex $newURL 0]
  368.             if {[llength [set nnn [lindex $newURL 1]]]} {
  369.                 set htmlActiveWidth [lindex $nnn 0]
  370.                 set htmlActiveHeight [lindex $nnn 1]
  371.             }
  372.             error "Continue!"
  373.         } else {
  374.             return
  375.         }
  376.     }
  377.  
  378.     if {$c != "\t"} {
  379.         set htmlURLTabSeen 0
  380.         return $c
  381.     }
  382.  
  383.     set matches {}
  384.     set attr $htmlActiveAttr
  385.     foreach w $URLs {
  386.         if {[string match "$curr*" $w]} {
  387.             lappend matches $w
  388.         }
  389.     }
  390.     if {![llength $matches]} {
  391.         beep
  392.     } else {
  393.         if {$htmlURLTabSeen} {
  394.             if {[catch {listpick -p ${htmlActiveUsed}:${htmlActiveAttr} $matches} ret]} {
  395.                 set ret ""
  396.             }
  397.             if {[string length $ret]} {
  398.                 set htmlActiveURL $ret
  399.                 error "Continue!"
  400.             }
  401.             set htmlURLTabSeen 0
  402.         } else {
  403.             set htmlURLTabSeen 1
  404.             set ret [string range [largestPrefix $matches] [string length $curr] end]
  405.         }
  406.         return $ret
  407.     }
  408.     return
  409. }
  410.  
  411. proc htmlStatusAskAttr {used attr required} {
  412.     global htmlAttrTabSeen htmlActiveInput
  413.  
  414.     set htmlAttrTabSeen 0
  415.     if {!$required} {
  416.         set pr "(optional) "
  417.     } else {
  418.         set pr {}
  419.     }
  420.     if {$used == "LI IN UL" || $used == "LI IN OL"} { # these two are special
  421.          append pr LI:$attr
  422.     } else {
  423.         append pr ${used}:$attr
  424.     }
  425.  
  426.     set v ""
  427.     while {[catch {statusPrompt $pr htmlAttrStatusFunc} v]} {
  428.         if {$v == "Cancel all!"} {
  429.             message "Cancel"
  430.             error
  431.         }
  432.         if {$v == "Continue!"} {
  433.             set v $htmlActiveInput
  434.             unset htmlActiveInput
  435.             break
  436.         }
  437.         if {$v == "Skip rest!"} {error "Skip rest!"}
  438.     }
  439.     
  440.     # Trim only if it's only spaces.
  441.     if {[string trim $v] == ""} {set v ""}
  442.      # if there are choices, check if the user has typed one.
  443.     set choices [htmlGetChoices $used]
  444.     
  445.     set matches {}
  446.     set areChoices [string match "*${attr}*" $choices]
  447.  
  448.     if {!$areChoices} {
  449.         return $v
  450.     } else {
  451.         foreach w $choices {
  452.             if {($used == "LI IN OL" || $used == "OL") && $attr == "TYPE="} { # special case
  453.                 set c ${attr}$v
  454.             } else {
  455.                 set c [string toupper "${attr}${v}*"]    
  456.             }
  457.             if {[string match "${c}*" $w]} {
  458.                 lappend matches  $w 
  459.             }
  460.         } 
  461.         # if unique extension, add what's needed, otherwise return nothing.
  462.         if {[llength $matches] == 1 && [string length $v]} {
  463.             set ret [string range $matches [string length $attr] end]
  464.             if {($used != "LI IN OL" && $used != "OL") || $attr != "TYPE="} {
  465.                 set ret [htmlSetCase $ret] 
  466.             }
  467.             return $ret
  468.         } else {
  469.             return
  470.         }
  471.     }
  472. }
  473.  
  474. # CDATA element attribute, status window match completion
  475. proc htmlAttrStatusFunc {curr c} {
  476.     global htmlActiveUsed htmlActiveAttr htmlAttrTabSeen htmlActiveInput
  477.  
  478.     if {$c == "\032"} {error "Cancel all!"}
  479.     if {$c == "\021"} {error "Skip rest!"}
  480.     # should we set the case or not (are there predefined choices)?
  481.     set choices [htmlGetChoices $htmlActiveUsed]
  482.     set matches {}
  483.     set attr $htmlActiveAttr
  484.     set areChoices [string match "*${attr}*" $choices]
  485.     foreach w $choices {
  486.         if {($htmlActiveUsed == "LI IN OL" ||  $htmlActiveUsed == "OL") \
  487.             && $attr == "TYPE="} {     # special case
  488.             if {[string match "${attr}${curr}*" $w]} {
  489.                 lappend matches [string range $w [string length $attr] end]
  490.             }
  491.         } elseif {[string match [string toupper "${attr}${curr}*"] $w]} {
  492.             lappend matches [string range $w [string length $attr] end]
  493.         }
  494.     }
  495.     
  496.     if {$c != "\t" } {
  497.         set htmlAttrTabSeen 0
  498.         if {$areChoices} {
  499.         # check if the last character matches
  500.             set matches {}
  501.             foreach w $choices {
  502.                 if {[string match [string toupper "${attr}${curr}${c}*"] $w]} {
  503.                     lappend matches [string range $w [string length $attr] end]
  504.                 }
  505.             }
  506.             if {[llength $matches]} { 
  507.                 if {($htmlActiveUsed != "LI IN OL" &&  $htmlActiveUsed != "OL") \
  508.                     || $attr != "TYPE="} { # special case 
  509.                     set c [htmlSetCase $c] 
  510.                 }
  511.                 return $c
  512.             } else {
  513.                 beep
  514.                 return
  515.             } 
  516.         } else {
  517.             return $c
  518.         }
  519.     }
  520.     
  521.     # it's a tab
  522.     if {![llength $matches]} {
  523.         beep
  524.     } else {
  525.         if {$htmlAttrTabSeen} {
  526.             if {[catch {listpick -p ${htmlActiveUsed}:${htmlActiveAttr} $matches} ret]} {
  527.                 set ret ""
  528.             }
  529.             if {[string length $ret]} {
  530.                 set htmlActiveInput $ret
  531.                 error "Continue!"
  532.             }
  533.             set htmlAttrTabSeen 0
  534.         } else {
  535.             set htmlAttrTabSeen 1
  536.             set ret [string range [largestPrefix $matches] [string length $curr] end]
  537.         }
  538.         if {($htmlActiveUsed != "LI IN OL" &&  $htmlActiveUsed != "OL") \
  539.         || $attr != "TYPE="} { 
  540.             # special case 
  541.             set ret [htmlSetCase $ret] 
  542.         }
  543.         return $ret
  544.     }
  545.     return
  546. }
  547.  
  548. # ask for an attribute which is a number. Returns "" if input is not valid.
  549. proc htmlAskNumber {item attr required} {
  550.     global HTMLmodeVars  htmlActiveWidth htmlActiveHeight
  551.     
  552.     set promptNoisily    $HTMLmodeVars(promptNoisily)
  553.     
  554.     # loop until input is valid, then something is returned
  555.     while {1} { 
  556.         if {$promptNoisily} {beep}
  557.         set pr ""
  558.         if {!$required} { set pr "(optional) "}
  559.         # these two are special
  560.         if {$item == "LI IN UL" || $item == "LI IN OL"} { 
  561.             append pr LI:$attr
  562.         } else {
  563.             append pr ${item}:$attr
  564.         }
  565.         if {$item == "IMG" && $attr == "WIDTH=" && [string length $htmlActiveWidth]} {
  566.             append pr " \[$htmlActiveWidth\] "
  567.         } elseif {$item == "IMG" && $attr == "HEIGHT=" && [string length $htmlActiveHeight]} {
  568.             append pr " \[$htmlActiveHeight\] "
  569.         }
  570.         
  571.         while {[catch {statusPrompt $pr htmlNumberStatusFunc} r]} { 
  572.             if {$r == "Cancel all!"} {
  573.                 message "Cancel"
  574.                 error
  575.             }
  576.             if {$r == "Skip rest!"} {error "Skip rest!"}
  577.         }
  578.         
  579.         set r [string trim $r]
  580.         # if no input, just return
  581.         if {![string length $r]} {
  582.             if {$item == "IMG" && $attr == "WIDTH="} {
  583.                 return $htmlActiveWidth
  584.             } elseif {$item == "IMG" && $attr == "HEIGHT="} {
  585.                 return $htmlActiveHeight
  586.             } else {
  587.                 return
  588.             }
  589.         }
  590.         # check that input is valid.
  591.         set numcheck [htmlCheckAttrNumber $item $attr $r]
  592.         if {$numcheck == 1} {
  593.             return $r 
  594.         } else {
  595.             alertnote "Invalid input. $numcheck"
  596.         }
  597.     }
  598. }
  599.  
  600. proc htmlNumberStatusFunc {curr c} {
  601.  
  602.     if {$c == "\032"} {error "Cancel all!"}
  603.     if {$c == "\021"} {error "Skip rest!"}
  604.     if {[lsearch -exact {+ - 0 1 2 3 4 5 6 7 8 9 %} $c] >=0 } {
  605.         return $c
  606.     } else {
  607.         beep
  608.     }
  609. }
  610.  
  611. # Force yes or no in the status window
  612. proc htmlStatusAskYesOrNo {curr c} {
  613.     if {$c == "\032"} {error "Cancel all!"}
  614.     if {$c == "\021"} {error "Skip rest!"}
  615.     set c [string tolower $c]
  616.     if {![string length $curr]} {
  617.         if {$c == "n"} {return "no"}
  618.         if {$c == "y"} {return "yes"}
  619.     }
  620.     beep
  621.     return
  622. }
  623.  
  624. # From menu, customize list of attributes which get asked about
  625. proc htmlUseAttrs {item} {
  626.     global HTMLmodeVars htmlPackageToUse modifiedVars
  627.     global htmlElemAttrUsed htmlElemAttrUsed3
  628.     global htmlElemAttrMore htmlElemAttrMore3
  629.     
  630.     set reqattrs [htmlGetRequired $item]
  631.     set used [htmlGetUsed $item]
  632.     set askformore [htmlGetAttrMore $item]
  633.     set optatts [htmlGetOptional $item]
  634.     set attrnumber [llength $optatts]
  635.     
  636.     set height [expr 95 + (( $attrnumber - 1) / 3 + 1) * 20]
  637.     set box "-w 400 -h $height -b OK 20 [expr $height - 30]  85 [expr $height - 10] \
  638.         -b Cancel 110 [expr $height - 30] 175 [expr $height - 10] \
  639.         -t {Select the optional attributes you want for $item} 10 10 450 30 "
  640.  
  641.     lappend box -t {Ask for more?} 10 [expr $height - 55] 110 [expr $height - 40] \
  642.         -r Yes $askformore 120 [expr $height - 55] 160 [expr $height - 40] \
  643.         -r No [expr !$askformore] 180 [expr $height - 55] 220 [expr $height - 40]
  644.     # see which attributes were used previously
  645.     set wpos 10 
  646.     set hpos 35
  647.     foreach attr $optatts {
  648.         if {[lsearch -exact $used $attr] >= 0} {
  649.             set checked 1
  650.         } else {
  651.             set checked 0
  652.         }
  653.         lappend box -c [string trimright $attr =] $checked $wpos $hpos [expr $wpos + 120] [expr $hpos + 15]
  654.         set wpos [expr $wpos + 130]
  655.             if {$wpos > 310} {
  656.                 set wpos 10
  657.                 set hpos [expr $hpos + 20]
  658.         }
  659.     }
  660.     # get the new ones wanted
  661.     set newatts [eval [concat dialog $box]]
  662.     set newuse {}
  663.     if {[lindex $newatts 0]} {
  664.         for {set i 0} {$i < $attrnumber} {incr i} {
  665.         if {[lindex $newatts [expr $i + 4]]} {
  666.                 lappend newuse [lindex $optatts $i]
  667.             }
  668.         }
  669.         set newuse [concat $reqattrs $newuse]
  670.         if {$htmlPackageToUse == 1} {
  671.             set num ""
  672.         } else {
  673.             set num 3
  674.         }
  675.         set htmlElemAttrUsed${num}($item) $newuse
  676.         addArrDef htmlElemAttrUsed$num $item $newuse
  677.         set htmlElemAttrMore${num}($item) [lindex $newatts 2]
  678.         addArrDef htmlElemAttrMore$num $item [lindex $newatts 2]
  679.     }
  680. }
  681.  
  682.